home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 January / enter-2004-01.iso / files / maxima-5.9.0.exe / {app} / share / maxima / 5.9.0 / src / numerical / f2cl-lib.lisp next >
Encoding:
Text File  |  2003-02-09  |  42.9 KB  |  1,397 lines

  1. ; macros.l - all the basic macros
  2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3. ;;;;;;;;Copyright (c) University of Waikato;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4. ;;;;;;;;Hamilton, New Zeland 1992-95 - all rights reserved;;;;;;;;;;;;;;;;
  5. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  6. (in-package :f2cl-lib)
  7.  
  8. ; macros:
  9. ;    rexpt
  10. ;    fexport
  11. ;    fproclaim
  12. ;    fuse-package 
  13. ;    fin-package
  14. ;    map-defvar
  15. ;    do1 
  16. ;    do!
  17. ;    double-cdr
  18. ;    putproperty
  19. ;    defprop
  20. ;    array-cl
  21. ;    store-cl
  22. ;    apply!
  23.  
  24. ;    rfref
  25. ;    rfset
  26. ;    fref
  27. ;    fset
  28.  
  29. ;    while
  30. ;       fdo
  31. ;    reset-vble - a defun
  32. ;       arithmetic-if
  33. ;    computed-goto
  34. ;    assigned-goto
  35. ;    eqv
  36. ;    constant-list
  37. ;----------------------------------------------------------------------------
  38.  
  39. (eval-when (compile load eval) (proclaim '(special *verbose*)))
  40. ;----------------------------------------------------------------------------
  41. #+aclpc (defmacro rexpt (x y) `(realpart (expt ,x ,y)))
  42. #-aclpc (defmacro rexpt (x y) `(expt ,x ,y))
  43.  
  44. (defvar *check-array-bounds* nil
  45.   "If non-NIL, generated code checks for array bounds.  If NIL, checking
  46. is not included")
  47.  
  48. ;;------------------------------------------------------------------------------
  49. ;;
  50. ;; Define the equivalent types between Fortran and Lisp.  This MUST
  51. ;; match the types given in f2cl1.l so keep it in sync!
  52. (deftype logical ()
  53.   `(member t nil))
  54.  
  55. ;; Decide what you want integer*4 to be.  Good choices are fixnum or
  56. ;; (signed-byte 32).  The latter is good only if your compiler does a
  57. ;; good job with this type.  If you aren't sure, use fixnum.  CMUCL
  58. ;; does a good job with (signed-byte 32).
  59. ;;
  60. ;; If you change this, you may need to change some of the macros
  61. ;; below, such as INT and AINT!
  62.  
  63. #+cmu
  64. (deftype integer4 ()
  65.   `(signed-byte 32))
  66. #-cmu
  67. (deftype integer4 ()
  68.   'fixnum)
  69.  
  70. (deftype integer2 ()
  71.   `(signed-byte 16))
  72. (deftype integer1 ()
  73.   `(signed-byte 8))
  74. (deftype real8 ()
  75.   'double-float)
  76. (deftype real4 ()
  77.   'single-float)
  78. (deftype complex8 ()
  79.   `(complex single-float))
  80. (deftype complex16 ()
  81.   `(complex double-float))
  82.  
  83. (deftype array-double-float ()
  84.     `(array double-float (*)))
  85. (deftype array-integer4 ()
  86.     `(array integer4 (*)))
  87. (deftype array-single-float ()
  88.     `(array single-float (*)))
  89. (deftype array-strings ()
  90.   `(array string (*)))
  91.  
  92. (defconstant %false% nil)
  93. (defconstant %true% t)
  94. ;;------------------------------------------------------------------------------
  95.  
  96. ;;-----------------------------------------------------------------------------
  97.  
  98. ;; Array dimensions are (d1, d2, d3, ...)
  99. ;;
  100. ;; Then x(n1, n2, n3, ...) means index is
  101. ;;
  102. ;; n1 + d1*(n2 + d2*(n3 + d3*(n4 + d4*(n5))))
  103.  
  104. ;; Return an expression that computes the column major index given the
  105. ;; indices and the bounds on each dimension.  The bounds are a list of
  106. ;; the upper and lower bounds for each dimension.
  107. (defun col-major-index (indices dims)
  108.   (flet ((get-offset (n bound)
  109.        (let ((lo (first bound)))
  110.          (if (and (numberp lo) (zerop lo))
  111.          n
  112.          `(the fixnum (- (the fixnum ,n) (the fixnum ,lo))))))
  113.      (get-size (bound)
  114.        (destructuring-bind (lo hi)
  115.            bound
  116.          (cond ((numberp lo)
  117.             (cond ((numberp hi)
  118.                (1+ (- hi lo)))
  119.               ((= lo 1)
  120.                hi)
  121.               (t
  122.                `(- ,hi ,(- lo 1)))))
  123.            (t
  124.             `(the fixnum (- ,hi (the fixnum (- (the fixnum ,lo) 1)))))))))
  125.     (let* ((rev-idx (reverse indices))
  126.        (rev-dim (reverse dims))
  127.        (idx (get-offset (first rev-idx) (first rev-dim))))
  128.       (do ((d (rest rev-dim) (rest d))
  129.        (n (rest rev-idx) (rest n)))
  130.       ((endp d)
  131.        idx)
  132.     (setf idx `(the fixnum (+ ,(get-offset (first n) (first d))
  133.                   (the fixnum (* ,(get-size (first d)) ,idx)))))))))
  134.  
  135. (defun check-array-bounds (indices bounds)
  136.   `(and ,@(mapcar #'(lambda (idx dim)
  137.              `(<= ,(first dim) ,idx ,(second dim)))
  138.          indices bounds)))
  139.  
  140. (defmacro fref (arr indices bounds &optional offset)
  141.   (if *check-array-bounds*
  142.       `(aref ,arr (if ,(check-array-bounds indices bounds)
  143.               (the fixnum (+ (the fixnum ,(or offset 0)) ,(col-major-index indices bounds)))
  144.               (error "Out of bounds index for array ~S"
  145.                  ',arr)))
  146.       `(aref ,arr (the fixnum (+ (the fixnum ,(or offset 0)) ,(col-major-index indices bounds))))))
  147.  
  148. (defmacro fset (a b) 
  149.   `(setf (fref ,(second a) ,@(cddr a)) ,b))
  150.  
  151. (defmacro fref-string (s range)
  152.   `(subseq ,s (1- ,(first range)) ,(second range)))
  153.  
  154. (defmacro fset-string (a b)
  155.   `(setf (fref-string ,(second a) ,(third a)) ,b))
  156.  
  157. (defmacro f2cl-// (a b)
  158.   `(concatenate 'string ,a ,b))
  159.  
  160. ;; (with-array-data ((data-var offset-var array))
  161. ;;   ...
  162. ;; )
  163.  
  164. (defun find-array-data (array)
  165.   (declare (type (array * (*)) array))
  166.   (let ((offset 0))
  167.     (declare (type fixnum offset)
  168.          (optimize (speed 3) (safety 0)))
  169.     (loop
  170.     (multiple-value-bind (displaced-to index-offset)
  171.         (array-displacement array)
  172.       (when (null displaced-to)
  173.         (return-from find-array-data (values array offset)))
  174.       (incf offset index-offset)
  175.       (setf array displaced-to)))))
  176.  
  177. (defmacro with-array-data ((data-var offset-var array) &rest body)
  178.   `(multiple-value-bind (,data-var ,offset-var)
  179.     (find-array-data ,array)
  180.     ,@body))
  181.  
  182. ;; Create an array slice for the array named VNAME whose elements are
  183. ;; of type TYPE.  The slice starts at the indices INDICES and the
  184. ;; original array has dimensions given by BOUND.
  185. ;;
  186. ;; This is done by making a displaced array to VNAME with the
  187. ;; appropriate offset.
  188. #+nil
  189. (defmacro array-slice (vname type indices bounds)
  190.   (let ((dims `(* ,@(mapcar #'(lambda (idx bnd)
  191.                 (if (and (numberp idx)
  192.                      (numberp (second bnd)))
  193.                     (+ (- (second bnd) idx) 1)
  194.                     `(+ (- ,(second bnd) ,idx) 1)))
  195.                 indices bounds))))
  196.     `(make-array ,dims
  197.       :element-type ',type
  198.       :displaced-to ,vname
  199.       :displaced-index-offset ,(col-major-index indices bounds))))
  200.  
  201. (defmacro array-slice (vname type indices bounds)
  202.   ;; To figure the size of the sliced array, use ARRAY-TOTAL-SIZE
  203.   ;; instead of the f2cl derived/declared BOUNDS, just in case we
  204.   ;; screwed up or in case we changed the size of the array in some
  205.   ;; other way.  This isn't possible in a function, but the array
  206.   ;; might be in a common block and we could change the dimensions of
  207.   ;; the common block at runtime.  (Some Fortran code like mpfun does
  208.   ;; this, although it's actually illegal.  Neat hack to "dynamically"
  209.   ;; change the dimensions.  Of course, for this to work in Fortran,
  210.   ;; the common block has to contain exactly that one array, or the
  211.   ;; array must be the last element of the common block.)
  212.   `(make-array (- (array-total-size ,vname) ,(col-major-index indices bounds))
  213.     :element-type ',type
  214.     :displaced-to ,vname
  215.     :displaced-index-offset ,(col-major-index indices bounds)))
  216.  
  217. #+nil
  218. (defmacro array-slice (vname type indices bounds)
  219.   (declare (ignore type indices bounds))
  220.   vname)
  221.  
  222. ;; Compute an initializer for make-array given the data in the list
  223. ;; DATA.  The array has en element type of TYPE and has dimensions of
  224. ;; DIMS.
  225. (defmacro array-initialize (type dims data)
  226.   (let ((data-list (gensym))
  227.     (data-len (length data))
  228.     (total-length (gensym)))
  229.     `(let* ((,data-list ',data)
  230.         (,total-length (reduce #'* (list ,@dims))))
  231.        (cond ((< ,data-len ,total-length)
  232.           ;; Need to append some data.
  233.           (append ,data-list (make-list (- ,total-length ,data-len)
  234.                         :initial-element (coerce 0 ',type))))
  235.          ((> ,data-len ,total-length)
  236.           ;; Need to truncate some data
  237.           (subseq ,data-list 0 ,total-length))
  238.          (t
  239.           ,data-list)))))  
  240.  
  241. ;----------------------------------------------------------------------------
  242.  
  243. #-aclpc (defmacro while (con &rest body)
  244.             `(loop (if (not ,con) (return t)) ,@body))
  245. ;------------------------------------------------------------------
  246.  
  247. (defmacro fortran_comment (&rest args)
  248.   (declare (ignore args)))
  249.  
  250. ;----------------------------------------------------------------------------
  251. ; fdo has similar syntax as do except there will only be one do_vble
  252.  
  253. (defmacro fdo (do_vble_clause predicate_clause &rest body)
  254.   (let ((step (gensym "STEP-"))
  255.     (iteration_count (gensym "CNT-")))
  256.     `(prog* ((,step ,(third (third do_vble_clause)))
  257.          (,iteration_count 
  258.           (max 0 (the integer4
  259.                (truncate (the integer4
  260.                    (+ (the integer4 (- ,(third (first predicate_clause))
  261.                                ,(second do_vble_clause)))
  262.                       ,step))
  263.                  ,step))
  264.            )))
  265.       (declare (type integer4 ,step ,iteration_count))
  266.       ;; initialise loop variable
  267.       (setq ,(first do_vble_clause) ,(second do_vble_clause))
  268.       loop
  269.       (return
  270.     (cond                ; all iterations done
  271.       ((zerop ,iteration_count) nil)
  272.       ;; execute loop, in/de-crement loop vble and decrement cntr
  273.       ,(cons 't 
  274.          (append 
  275.           (append body
  276.               `((setq ,(first do_vble_clause) (the integer4 ,(third do_vble_clause))
  277.                  ,iteration_count (the integer4 (1- ,iteration_count)))))
  278.           '((go loop)))))))))
  279.  
  280. ;(defmacro fdo (do-vbles predicate-clause &rest body)
  281. ;   `(prog nil
  282. ;          (setq ,(caar do-vbles) ,(cadar do-vbles)) 
  283. ;          loop
  284. ;          (return
  285. ;          (cond ,(reset-vble predicate-clause)
  286. ;                ,(cons 't 
  287. ;                       (append 
  288. ;                        (append body `((setq ,(caar do-vbles) ,(caddar do-vbles))))
  289. ;                        '((go loop))))))))
  290. ;(defmacro fdo (do-vbles predicate-clause &rest body)
  291. ;   `(prog (iteration-count)
  292. ;          ,(append '(psetq) 
  293. ;                   (do ((do-vars do-vbles (cdr do-vars))
  294. ;                        (ret nil (append ret (list (caar do-vars) (cadar do-vars)))))
  295. ;                       ((null do-vars) ret)))
  296. ;          loop
  297. ;          (return
  298. ;          (cond ,predicate-clause
  299. ;                ,(cons 't 
  300. ;                       (append 
  301. ;                        (append body
  302. ;                                (list
  303. ;                                (append '(psetq)
  304. ;                                (do ((do-vars do-vbles (cdr do-vars))
  305. ;                                     (ret nil (append ret (if (null (caddar do-vars)) 
  306. ;                                                              nil 
  307. ;                                                              (list (caar do-vars) 
  308. ;                                                                    (caddar do-vars))))))
  309. ;                                    ((null do-vars) ret)))))
  310. ;                        '((go loop))))))))
  311.  
  312. ;----------------------------------------------------------------------------
  313. ;; macro for division 
  314.  
  315. (defmacro f2cl/ (x y)
  316.   (let ((top (gensym))
  317.     (bot (gensym)))
  318.     `(let ((,top ,x)
  319.        (,bot ,y))
  320.       (if (and (typep ,top 'integer)
  321.            (typep ,bot 'integer))
  322.       (values (the integer4 (truncate ,top ,bot)))
  323.       (/ ,top ,bot)))))
  324.  
  325. (defmacro int-add (arg &rest more-args)
  326.   (if (null more-args)
  327.       arg
  328.       (if (> (length more-args) 1)
  329.       `(the integer4 (+ ,arg (int-add ,@more-args)))
  330.       `(the integer4 (+ ,arg ,@more-args)))))
  331.  
  332. (defun convert-int-sub (args)
  333.   (let ((nargs (length args)))
  334.     (case nargs
  335.       (1
  336.        `(the integer4 (- ,(first args))))
  337.       (2
  338.        `(the integer4 (- ,(first args) ,(second args))))
  339.       (t
  340.        (let ((result `(the integer4 (- ,(first args) ,(second args)))))
  341.      (dolist (arg (rest (rest args)))
  342.        (setf result `(the integer4 (- ,result ,arg))))
  343.      result)))))
  344.  
  345. (defmacro int-sub (&rest args)
  346.   (convert-int-sub args))
  347.   
  348. (defmacro int-mul (arg &rest more-args)
  349.   (if (null more-args)
  350.       arg
  351.       (if (> (length more-args) 1)
  352.       `(the integer4 (* ,arg (int-mul ,@more-args)))
  353.       `(the integer4 (* ,arg ,@more-args)))))
  354.  
  355.  
  356. ;; macro for a lisp equivalent of Fortran arithmetic IFs
  357. (defmacro arithmetic-if (pred s1 s2 s3)
  358.   (let ((tst (gensym)))
  359.     `(let ((,tst ,pred))
  360.       (cond ((< ,tst 0) ,s1)
  361.         ((= ,tst 0) ,s2)
  362.         (t ,s3)))))
  363.  
  364. ;; macro for a lisp equivalent of Fortran computed GOTOs
  365. (defun computed-goto-aux (tags)
  366.   (let ((idx 0)
  367.     (result '()))
  368.     (dolist (tag tags (nreverse result))
  369.       (incf idx)
  370.       (push `(,idx (go ,tag)) result))))
  371.  
  372. (defmacro computed-goto (tag-lst i)
  373.   `(case ,i
  374.     ,@(computed-goto-aux tag-lst)))
  375.  
  376. ;; macro for a lisp equivalent of Fortran assigned GOTOs
  377. (defmacro assigned-goto (i &optional tag-lst)
  378.    `(if ,tag-lst
  379.         (if (member ,i ,tag-lst) 
  380.             (go ,i)
  381.             (error "bad statement number in assigned goto"))
  382.         (go ,i)))
  383.  
  384. ;;-----------------------------------------------------------------------------
  385. ;;
  386. ;; Define the intrinsic functions
  387. ;;
  388. ;; Reference:  The Fortran 77 standard found at www.fortran.com.  Section 15.10
  389.  
  390. ;; INT is the generic name as well as the integer version.  IFIX is
  391. ;; the same.  IDINT is the double version.
  392.  
  393. (declaim (inline int ifix idfix))
  394.  
  395. #-cmu
  396. (defun int (x)
  397.   ;; We use fixnum here because f2cl thinks Fortran integers are
  398.   ;; fixnums.  If this should change, we need to change the ranges
  399.   ;; here as well.
  400.   (etypecase x
  401.     (integer
  402.      (the integer4 x))
  403.     (single-float
  404.      (truncate (the (single-float #.(float most-negative-fixnum)
  405.                   #.(float most-positive-fixnum))
  406.          x)))
  407.     (double-float
  408.      (truncate (the (double-float #.(float most-negative-fixnum 1d0)
  409.                   #.(float most-positive-fixnum 1d0))
  410.          x)))))
  411.  
  412. #+cmu
  413. (defun int (x)
  414.   ;; For CMUCL, we support the full 32-bit integer range, so INT can
  415.   ;; return a full 32-bit integer.  Tell CMUCL that this is true so we
  416.   ;; generate fast code.  If this is not true, the original Fortran
  417.   ;; code was wrong.
  418.   (etypecase x
  419.     (integer
  420.      (the integer4 x))
  421.     (single-float
  422.      (the integer4
  423.        (truncate (the (single-float #.(float (- (ash 1 31)))
  424.                     #.(float (1- (ash 1 31))))
  425.            x))))
  426.     (double-float
  427.      (the integer4
  428.        (truncate (the (double-float #.(float (- (ash 1 31)) 1d0)
  429.                     #.(float (1- (ash 1 31)) 1d0))
  430.            x))))))
  431.   
  432. (defun ifix (x)
  433.   (int x))
  434. (defun idfix (x)
  435.   (int x))
  436.  
  437. ;; AINT is the generic and specific function for real; DINT, for
  438. ;; double.  It truncates its arg towards zero and returns the integer
  439. ;; as a floating-point number of the same type as its arg.
  440. ;;
  441. ;; ANINT is the generic and specific function for real; DNINT, for
  442. ;; double. It rounds to the nearest integer and returns the result as
  443. ;; a float of the same type.
  444. ;;
  445. ;; NINT is the generic and specific function for real; IDNINT, for
  446. ;; double.  Does the same as ANINT, but the result is an integer.
  447.  
  448. (declaim (inline aint dint anint dnint nint idnint))
  449.  
  450. (defun aint (x)
  451.   ;; ftruncate is exactly what we want.
  452.   (etypecase x
  453.     (single-float
  454.      (ftruncate (the single-float x)))
  455.     (double-float
  456.      (ftruncate (the double-float x)))))
  457.  
  458. (defun dint (x)
  459.   (aint x))
  460.  
  461. (defun anint (x)
  462.   (values (fround x)))
  463. (defun dnint (x)
  464.   (values (fround x)))
  465. (defun nint (x)
  466.   (values (round x)))
  467. (defun idnint (x)
  468.   (values (round x)))
  469.  
  470. ;; Type conversion
  471. ;;
  472. ;; FREAL is F2CL's version of the Fortran REAL which takes converts
  473. ;; its arg to a real.  SNGL is the same.  DBLE returns a double.  They
  474. ;; also return the real part of a complex number.  CMPLX takes one or
  475. ;; two args and creates a complex number.
  476.  
  477. (declaim (inline freal sngl dble cmplx))
  478. (defun freal (x)
  479.   (coerce (realpart x) 'single-float))
  480.  
  481. (defun sngl (x)
  482.   (coerce (realpart x) 'single-float))
  483.  
  484. (defun dble (x)
  485.   (coerce (realpart x) 'double-float))
  486.  
  487. (defun cmplx (x &optional y)
  488.   (complex x (if y y 0)))
  489.  
  490. (defun ichar (c)
  491.   (char-int c))
  492. (defun fchar (i)            ;intrinsic function char
  493.   (char-int i))
  494.  
  495. (declaim (inline iabs dabs cabs amod dmod))
  496. #-aclpc
  497. (defun iabs (x)
  498.   (declare (type integer4 x))
  499.   (abs x))
  500. (defun dabs (x)
  501.   (declare (type double-float x))
  502.   (abs x))
  503. (defun cabs (x)
  504.   (declare (type complex x))
  505.   (abs x))
  506.  
  507. (defun amod (x y)
  508.   (declare (type single-float x y))
  509.   (mod x y))
  510. (defun dmod (x y)
  511.   (declare (type double-float x y))
  512.   (mod x y))
  513.  
  514.  
  515. ;; Transfer of sign.  SIGN is the generic and specific function for
  516. ;; real.  ISIGN is for integers; DSIGN for doubles.  Basically
  517. ;; computes sign(a2)*|a1|.
  518.  
  519. (declaim (inline isign sign dsign))
  520.  
  521. (defun isign (x y)
  522.   (declare (type integer4 x y))
  523.   (if (>= y 0)
  524.       (the integer4 (abs x))
  525.       (the integer4 (- (the integer4 (abs x))))))
  526.  
  527. ;; Fortran 77 says SIGN is a generic!
  528. (defun sign (x y)
  529.   (declare (type (or integer4 single-float double-float) x y))
  530.   (etypecase x
  531.     (integer4
  532.      (isign x y))
  533.     (single-float
  534.      (float-sign y x))
  535.     (double-float
  536.      (float-sign y x))))
  537.  
  538. (defun dsign (x y)
  539.   (declare (type double-float x y))
  540.   (float-sign y x))
  541.  
  542. ;; Positive difference.  DIM is the generic and specific function for
  543. ;; real.  IDIM is for integers; DDIM, doubles.
  544. ;;
  545. ;; If a1 > a2, returns a1-a2, otherwise 0.  Basically the same as
  546. ;; max(0, a1-a2).
  547. (declaim (inline idim dim ddim))
  548. (defun idim (x y)
  549.   (declare (type integer4 x y))
  550.   (max 0 (- x y)))
  551.  
  552. (defun dim (x y)
  553.   (declare (type (or integer4 single-float double-float) x y))
  554.   (etypecase x
  555.     (integer4
  556.      (max 0 (- x y)))
  557.     (single-float
  558.      (max 0f0 (- x y)))
  559.     (double-float
  560.      (max 0d0 (- x y)))))
  561.  
  562. (defun ddim (x y)
  563.   (declare (type double-float x y))
  564.   (max 0d0 (- x y)))
  565.  
  566. ;; Double-precision product.  How this is done isn't specified, but I
  567. ;; suspect the real args are converted to doubles and then the product
  568. ;; is computed.
  569. (defun dprod (x y)
  570.   (declare (single-float x y))
  571.   (* (float x 1d0) (float y 1d0)))
  572.  
  573. ;; The max and min functions.
  574. ;;
  575. ;; MAX is the generic. MAX0, AMAX1, and DMAX1 returns the max of the
  576. ;; args with the same type as the args.
  577. ;;
  578. ;; AMAX0 takes integer args and returns the max as a real. MAX1 takes
  579. ;; real args and returns the max as a integer.  (How the conversion is
  580. ;; done isn't specified.)
  581. ;;
  582. ;; Should we make these macros that expand directly to the appropriate
  583. ;; max?
  584. (defun max0 (x y &rest z)
  585.   #-gcl(declare (integer x y))
  586.   (apply #'max x y z))
  587. (defun amax1 (x y &rest z)
  588.   #-gcl(declare (single-float x y))
  589.   (apply #'max x y z))
  590. (defun dmax1 (x y &rest z)
  591.   #-gcl(declare (double-float x y))
  592.   (apply #'max x y z))
  593. (defun max1 (x y &rest z)
  594.   #-gcl(declare (single-float x y))
  595.   (int (apply #'max x y z)))
  596. (defun amax0 (x y &rest z)
  597.   #-gcl(declare (integer4 x y))
  598.   (float (apply #'max x y z) 1f0))
  599.  
  600. (defun min0 (x y &rest z)
  601.   (apply #'min x y z))
  602. (defun amin1 (x y &rest z)
  603.   (apply #'min x y z))
  604. (defun dmin1 (x y &rest z)
  605.   (apply #'min x y z))
  606.  
  607. (defun amin0 (x y &rest z)
  608.   (float (apply #'min x y z)))
  609. (defun min1 (x y &rest z)
  610.   (nint (apply #'min x y z)))
  611.  
  612. ;; Define some compile macros for these max/min functions.
  613. #+cmu
  614. (progn
  615. (define-compiler-macro max0 (&rest args)
  616.   `(max ,@args))
  617. (define-compiler-macro amax1 (&rest args)
  618.   `(max ,@args))
  619. (define-compiler-macro dmax1 (&rest args)
  620.   `(max ,@args))
  621. (define-compiler-macro min0 (&rest args)
  622.   `(min ,@args))
  623. (define-compiler-macro amin1 (&rest args)
  624.   `(min ,@args))
  625. (define-compiler-macro dmin1 (&rest args)
  626.   `(min ,@args))
  627. (define-compiler-macro min1 (&rest args)
  628.   `(nint (min ,@args)))
  629.  
  630. (define-compiler-macro amax0 (&rest args)
  631.   `(float (max ,@args)))
  632. (define-compiler-macro max1 (&rest args)
  633.   `(nint (max ,@args)))
  634.  
  635. (define-compiler-macro amin0 (&rest args)
  636.   `(float (min ,@args)))
  637. (define-compiler-macro min1 (&rest args)
  638.   `(nint (min ,@args)))
  639. ) ; end progn
  640.  
  641. (defun len (s)
  642.   (length s))
  643.  
  644. (defun index (s1 s2)
  645.   (or (search s1 s2) 0))
  646.  
  647. ;; These string operations need some work!
  648. (defun lge (s1 s2)
  649.   (string>= s1 s2))
  650. (defun lgt (s1 s2)
  651.   (string> s1 s2))
  652. (defun lle (s1 s2)
  653.   (string<= s1 s2))
  654. (defun llt (s1 s2)
  655.   (string< s1 s2))
  656.  
  657. (defun fstring-/= (s1 s2)
  658.   (not (string= s1 s2)))
  659. (defun fstring-= (s1 s2)
  660.   (string= s1 s2))
  661. (defun fstring-> (s1 s2)
  662.   (string> s1 s2))
  663. (defun fstring->= (s1 s2)
  664.   (string>= s1 s2))
  665. (defun fstring-< (s1 s2)
  666.   (string< s1 s2))
  667. (defun fstring-<= (s1 s2)
  668.   (string<= s1 s2))
  669.  
  670.  
  671. ;; AIMAG: imaginary part of a complex number
  672. ;; CONJG: conjugate of a complex number
  673. (declaim (inline aimag conjg))
  674. (defun aimag (c)
  675.   (imagpart c))
  676. (defun conjg (c)
  677.   (conjugate c))
  678.  
  679. (declaim (inline fsqrt flog))
  680. (defun fsqrt (x)
  681.   (typecase x
  682.     (single-float
  683.      (sqrt (the (single-float 0f0) x)))
  684.     (double-float
  685.      (sqrt (the (double-float 0d0) x)))
  686.     (t
  687.      (sqrt x))))
  688.  
  689. (defun flog (x)
  690.   (typecase x
  691.     (single-float
  692.      (log (the (or (single-float (0f0)) (member 0f0)) x)))
  693.     (double-float
  694.      (log (the (or (double-float (0d0)) (member 0d0)) x)))
  695.     (t
  696.      (log x))))
  697.   
  698. ;; Tell Lisp that the arguments always have the correct range.  If
  699. ;; this is not true, the original Fortran code was broken anyway, so
  700. ;; GIGO (garbage in, garbage out).
  701.  
  702. (declaim (inline dsqrt csqrt alog dlog clog alog10 dlog10))
  703. (defun dsqrt (x)
  704.   (declare (type (double-float 0d0) x))
  705.   (sqrt  x))
  706. (defun csqrt (x)
  707.   (sqrt x))
  708. (defun alog (x)
  709.   (declare (type (or (single-float (0f0)) (member 0f0)) x))
  710.   (log x))
  711. (defun dlog (x)
  712.   (declare (type (or (double-float (0d0)) (member 0d0)) x))
  713.   (log x))
  714. (defun clog (x)
  715.   (log x))
  716. (defun alog10 (x)
  717.   (declare (type (or (single-float (0f0)) (member 0f0)) x))
  718.   (log x 10f0))
  719. (defun dlog10 (x)
  720.   (declare (type (or (double-float (0d0)) (member 0d0)) x))
  721.   (log x 10.0d0))
  722.  
  723. (declaim (inline log10))
  724. (defun log10 (x)
  725.   (typecase x
  726.     (single-float
  727.      (log (the (or (single-float (0.0f0)) (member 0f0)) x) 10f0))
  728.     (double-float
  729.      (log (the (or (double-float (0.0d0)) (member 0d0)) x) 10d0))
  730.     (t
  731.      (/ (log x)
  732.     (typecase x
  733.       ((complex double-float)
  734.        10d0)
  735.       ((complex single-float)
  736.        10f0)
  737.       (t
  738.        (coerce 10 (type-of (realpart x)))))))))
  739.  
  740. (declaim (inline dexp cexp))
  741. (defun dexp (x)
  742.   (declare (type double-float x))
  743.   (exp x))
  744. (defun cexp (x)
  745.   (declare (type complex x))
  746.   (exp x))
  747.  
  748. (declaim (inline dsin csin dcos ccos dtan ctan dasin dacos datan atan2 datan2 dsinh dcosh dtanh))
  749. (defun dsin (x)
  750.   (declare (type double-float x))
  751.   (sin x))
  752. (defun csin (x)
  753.   (declare (type complex x))
  754.   (sin x))
  755.  
  756. (defun dcos (x)
  757.   (declare (type double-float x))
  758.   (cos x))
  759. (defun ccos (x)
  760.   (declare (type complex x))
  761.   (cos x))
  762.  
  763. (defun dtan (x)
  764.   (declare (type double-float x))
  765.   (tan x))
  766. (defun ctan (x)
  767.   (declare (type complex x))
  768.   (tan x))
  769.  
  770. (defun dasin (x)
  771.   (declare (type double-float x))
  772.   (asin x))
  773. (defun dacos (x)
  774.   (declare (type double-float x))
  775.   (acos x))
  776. (defun datan (x)
  777.   (declare (type double-float x))
  778.   (atan x))
  779. (defun atan2 (x y)
  780.   (declare (type double-float x))
  781.   (atan x y))
  782. (defun datan2 (x y)
  783.   (declare (type double-float x y))
  784.   (atan x y))
  785.  
  786. (defun dsinh (x)
  787.   (declare (type double-float x))
  788.   (sinh x))
  789. (defun dcosh (x)
  790.   (declare (type double-float x))
  791.   (cosh x))
  792. (defun dtanh (x)
  793.   (declare (type double-float x))
  794.   (tanh x))
  795.  
  796. (declaim (inline ffloat))
  797. (defun ffloat (x)
  798.   (coerce x 'single-float))
  799.  
  800. #+nil
  801. (defun process-implied-do (ido low-bnds init)
  802.   (let* ((implied-do (remove '|,| ido))
  803.      (array (first implied-do))
  804.      (do-var (elt implied-do (1- (position '= implied-do))))
  805.      (limits (rest (member '= implied-do)))
  806.      (start (first limits))
  807.      (end (second limits))
  808.      (step (if (>= (length limits) 3)
  809.            (third limits)
  810.            1)))
  811.     (cond ((atom array)
  812.        `(do ((,do-var ,start (+ ,do-var ,step)))
  813.          ((> ,do-var ,end))
  814.          (declare (integer4 ,do-var))
  815.          (fset (fref ,array ,(remove '|,| (second implied-do)) ,low-bnds) (pop ,init))))
  816.       (t
  817.        `(do ((,do-var ,start (+ ,do-var ,step)))
  818.          ((> ,do-var ,end))
  819.          (declare (integer4 ,do-var))
  820.          ,(process-implied-do (remove '|,| array) low-bnds init))))))
  821.  
  822. (defun process-implied-do (ido low-bnds var-types init)
  823.   (destructuring-bind (data-vars (index-var start end &optional step))
  824.       ido
  825.     (labels
  826.     ((convert-type (type)
  827.        (if (eq type 'integer4)
  828.            `(truncate (pop ,init))
  829.            `(coerce (pop ,init) ',type)))
  830.      (map-vars (v)
  831.        (mapcar #'(lambda (x b vt)
  832.                `(fset (fref ,(first x) ,(second x) ((,b)))
  833.              ,(convert-type vt)))
  834.            v low-bnds var-types)))
  835.     `(do ((,index-var ,start (+ ,index-var ,(or step 1))))
  836.          ((> ,index-var ,end))
  837.        ,@(map-vars data-vars))
  838.     )))
  839.  
  840.  
  841. ;; Process implied do loops for data statements
  842. (defmacro data-implied-do (implied-do low-bnds var-types vals)
  843.   (let ((v (gensym)))
  844.     `(let ((,v ',vals))
  845.       ,(process-implied-do implied-do low-bnds var-types v))))
  846.  
  847. ;-----------------------------------------------------------------------------  ; end of macros.l
  848.    
  849. ;; Map Fortran logical unit numbers to Lisp streams
  850.  
  851. #-gcl
  852. (defparameter *lun-hash*
  853.   (let ((table (make-hash-table)))
  854.     (setf (gethash 6 table) *standard-output*)
  855.     (setf (gethash 5 table) *standard-input*)
  856.     (setf (gethash t table) *standard-output*)
  857.     table))
  858.  
  859. #+gcl
  860. (defvar *lun-hash*
  861.   (let ((table (make-hash-table)))
  862.     (setf (gethash 6 table) *standard-output*)
  863.     (setf (gethash 5 table) *standard-input*)
  864.     (setf (gethash t table) *standard-output*)
  865.     table))
  866.  
  867. #+nil
  868. (defun lun->stream (lun)
  869.   (let ((stream (gethash lun *lun-hash*)))
  870.     (if stream
  871.     stream
  872.     (setf (gethash lun *lun-hash*)
  873.           (open (format nil "fort~d.dat" lun)
  874.             :direction :output
  875.             :if-exists :rename)))))
  876.  
  877. (defun lun->stream (lun &optional readp)
  878.   (let ((stream (gethash lun *lun-hash*)))
  879.     (if stream
  880.     stream
  881.     (cond ((integerp lun)
  882.            (setf (gethash lun *lun-hash*)
  883.              (open (format nil "fort~d.dat" lun)
  884.                :direction :output
  885.                :if-exists :rename)))
  886.           ((stringp lun)
  887.            (setf (gethash lun *lun-hash*)
  888.              (if readp
  889.              (make-string-input-stream lun)
  890.              (make-string-output-stream))))
  891.           ))))
  892.  
  893. (defun init-fortran-io ()
  894.   "Initialize the F2CL Fortran I/O subsystem to sensible defaults"
  895.   (clrhash *lun-hash*)
  896.   (setf (gethash 6 *lun-hash*) *standard-output*)
  897.   (setf (gethash 5 *lun-hash*) *standard-input*)
  898.   (setf (gethash t *lun-hash*) *standard-output*))
  899.  
  900. (defun close-fortran-io ()
  901.   "Close all F2CL Fortran units (except for standard output and input)
  902. causing all pending operations to be flushed"
  903.   (maphash #'(lambda (key val)
  904.            (when (and (streamp val) (not (member key '(5 6 t))))
  905.          (format t "Closing unit ~A: ~A~%" key val)
  906.          (close val)))
  907.            *lun-hash*))
  908.  
  909. #-gcl
  910. (declaim (ftype (function (t) stream) lun->stream))
  911.  
  912. (defmacro fformat (dest-lun format-cilist &rest args)
  913.   (let ((stream (gensym)))
  914.     `(let ((,stream (lun->stream ,dest-lun)))
  915.       (execute-format-main ,stream ',format-cilist ,@args)
  916.       (when (stringp ,dest-lun)
  917.     (replace ,dest-lun (get-output-stream-string ,stream))))))
  918.  
  919. (defun execute-format (top stream format arg-list)
  920.   (do ((formats format (if (and top (null formats))
  921.                format
  922.                (rest formats))))
  923.       ((or (null arg-list)
  924.        (and (not top)
  925.         (null formats)))
  926.        ;;(format t "~&formats = ~S~%" formats)
  927.        (do ((more formats (rest more)))
  928.        ((not (stringp (first more))))
  929.      (format stream (first more)))
  930.        arg-list)
  931.     (when (null formats)
  932.       (setf formats format))
  933.     #+nil
  934.     (let ((*print-circle* t))
  935.       (format t "~&formats = ~S~%" formats))
  936.     (cond ((listp (first formats))
  937.        (format stream (caar formats) (pop arg-list)))
  938.       ((numberp (first formats))
  939.        ;; Repeat a group some fixed number of times
  940.        (dotimes (k (first formats))
  941.          ;;(format t "k = ~A, format = ~S~%" k (second formats))
  942.          (setf arg-list
  943.            (execute-format nil stream (second formats) arg-list)))
  944.        (setf formats (rest formats))
  945.        ;;(format t "  cont with format = ~S~%" formats)
  946.        )
  947.        ((eq (first formats) t)
  948.         ;; Repeat "forever" (until we run out of data)
  949.         (loop while arg-list do
  950.           (setf arg-list
  951.             (execute-format nil stream (second formats) arg-list))
  952.           ;; Output a newline after the repeat (I think Fortran says this)
  953.           (format stream "~%")))
  954.       (t
  955.        (format stream (car formats))))))
  956.        
  957.        
  958. (defun execute-format-main (stream format &rest args)
  959.   (let ((format-list (copy-tree format))
  960.     (arg-list (apply #'append (map 'list #'(lambda (x)
  961.                          (cond ((numberp x)
  962.                             (list x))
  963.                                ((stringp x)
  964.                             (list x))
  965.                                (t
  966.                             (coerce x 'list))))
  967.                        args))))
  968.     (execute-format t stream format-list arg-list)))
  969.  
  970.  
  971. #||
  972. (defmacro fformat1 (dest directive arg)
  973.   (let ((val (gensym)))
  974.     `(let ((,val ,arg))
  975.       (cond ((and (arrayp ,val)
  976.           (not (stringp ,val)))
  977.          (dotimes (k (array-total-size ,val))
  978.            (format ,dest ,directive (row-major-aref ,val k))
  979.            (terpri ,dest)))
  980.         ((listp ,val)
  981.          (dolist (item ,val)
  982.            (format ,dest ,directive item)
  983.            (terpri ,dest)))
  984.         (t
  985.          (format ,dest ,directive ,val))))))
  986.  
  987. (defun expand-format (dest cilist args)
  988.   (if (equal cilist '("~A~%"))
  989.       (append (mapcar #'(lambda (arg) `(fformat1 ,dest "~A " ,arg)) args)
  990.        `((format ,dest "~%")))
  991.  
  992.       ;loop through directives, consume arguments
  993.       (do ((res '())
  994.        (directives cilist (cdr directives))
  995.        (arglist args arglist))
  996.       ((null directives)
  997.        (nreverse res))
  998.     (cond ((stringp (first directives))
  999.            ;;(format t "~a~%" (first directives))
  1000.            (push `(format ,dest ,(first directives))
  1001.              res))
  1002.           (t
  1003.            (push `(fformat1 ,dest
  1004.                ,(car (first directives)) 
  1005.                ,(first arglist))
  1006.              res)
  1007.            (setq arglist (cdr arglist)))))))
  1008. ||#
  1009.  
  1010. ;; Initialize a multi-dimensional array of character strings. I think
  1011. ;; we need to do it this way to appease some picky compilers (like
  1012. ;; CMUCL).  The initial-element is needed to get rid of a warning
  1013. ;; about the default initial element not being a simple
  1014. ;; string. However, this initializes all elements of the array to
  1015. ;; exactly the same string, so we loop over the entire array contents
  1016. ;; and initialize each element with a string of the appropriate
  1017. ;; length.  The string is initialized with #\Space because it seems
  1018. ;; that's what Fortran initializes it to.
  1019. (defmacro f2cl-init-string (dims len)
  1020.   (let ((init (gensym))
  1021.     (new-dims (if (every #'numberp dims)
  1022.               `',dims
  1023.               `(list ,@dims))))
  1024.     `(let ((,init (make-array ,new-dims
  1025.                   :element-type `(simple-array base-char (,',@len))
  1026.                   :initial-element (make-string ,@len))))
  1027.        (dotimes (k (array-total-size ,init))
  1028.      (setf (aref ,init k)
  1029.            (make-string ,@len :initial-element #\Space)))
  1030.        ,init)))
  1031.  
  1032. ;; This macro is supposed to set LHS to the RHS assuming that the LHS
  1033. ;; is a Fortran CHARACTER type of length LEN.
  1034. ;;
  1035. ;; Currently, converts the RHS to the appropriate length string and
  1036. ;; assigns it to the LHS.  However, this can generate quite a bit of
  1037. ;; garbage.  We might want to be a bit smarter and use loops to
  1038. ;; replace the individual characters of the LHS with the appropriate
  1039. ;; characters from the RHS.
  1040. (defmacro f2cl-set-string (lhs rhs (string len))
  1041.   (declare (ignore string))
  1042.   (etypecase lhs
  1043.     (symbol
  1044.      ;; Assignment to a simple string.
  1045.      `(setf ,lhs (f2cl-string ,rhs ,len)))
  1046.     (list
  1047.      ;; Assignment to an array
  1048.      `(fset ,lhs (f2cl-string ,rhs ,len)))))
  1049.  
  1050. (defun f2cl-string (string len)
  1051.   ;; Create a string of the desired length by either appending spaces
  1052.   ;; or truncating the string.
  1053.   (let ((slen (length string)))
  1054.     (cond ((= slen len)
  1055.        ;; Need to make a copy of the string, so we don't have
  1056.        ;; duplicated structure.
  1057.        (copy-seq string))
  1058.       ((> slen len)
  1059.        ;; Truncate the string
  1060.        (subseq string 0 len))
  1061.       (t
  1062.        ;; String is too short, so append some spaces
  1063.        (concatenate 'string string (make-string (- len slen) :initial-element #\Space))))))
  1064.  
  1065.  
  1066. ;;; Strictly speaking, this is not part of Fortran, but so many
  1067. ;;; Fortran packages use these routines, we're going to add them here.
  1068. ;;; They're much easier to implement in Lisp than in Fortran!
  1069.  
  1070. ;;
  1071. ;;  DOUBLE-PRECISION MACHINE CONSTANTS
  1072. ;;  D1MACH( 1) = B**(EMIN-1), THE SMALLEST POSITIVE MAGNITUDE.
  1073. ;;  D1MACH( 2) = B**EMAX*(1 - B**(-T)), THE LARGEST MAGNITUDE.
  1074. ;;  D1MACH( 3) = B**(-T), THE SMALLEST RELATIVE SPACING.
  1075. ;;  D1MACH( 4) = B**(1-T), THE LARGEST RELATIVE SPACING.
  1076. ;;  D1MACH( 5) = LOG10(B)
  1077. ;;
  1078.  
  1079. #+gcl
  1080. (defconstant least-positive-normalized-double-float least-positive-double-float)
  1081. #+gcl
  1082. (defconstant least-positive-normalized-single-float least-positive-single-float)
  1083.  
  1084.  
  1085. (defun d1mach (i)
  1086.   (ecase i
  1087.     (1
  1088.      #-gcl least-positive-normalized-double-float
  1089.      #+gcl least-positive-double-float)
  1090.     (2 most-positive-double-float)
  1091.     (3 double-float-epsilon)
  1092.     (4 (scale-float double-float-epsilon 1))
  1093.     (5 (log (float (float-radix 1d0) 1d0) 10d0))))
  1094.  
  1095. (defun r1mach (i)
  1096.   (ecase i
  1097.     (1
  1098.      #-gcl least-positive-normalized-single-float
  1099.      #+gcl least-positive-single-float)
  1100.     (2 most-positive-single-float)
  1101.     (3 single-float-epsilon)
  1102.     (4 (scale-float single-float-epsilon 1))
  1103.     (5 (log (float (float-radix 1f0)) 10f0))))
  1104.  
  1105. ;;
  1106. ;;     This is the CMLIB version of I1MACH, the integer machine
  1107. ;;     constants subroutine originally developed for the PORT library.
  1108. ;;
  1109. ;;     I1MACH can be used to obtain machine-dependent parameters
  1110. ;;     for the local machine environment.  It is a function
  1111. ;;     subroutine with one (input) argument, and can be called
  1112. ;;     as follows, for example
  1113. ;;
  1114. ;;          K = I1MACH(I)
  1115. ;;
  1116. ;;     where I=1,...,16.  The (output) value of K above is
  1117. ;;     determined by the (input) value of I.  The results for
  1118. ;;     various values of I are discussed below.
  1119. ;;
  1120. ;;  I/O unit numbers.
  1121. ;;    I1MACH( 1) = the standard input unit.
  1122. ;;    I1MACH( 2) = the standard output unit.
  1123. ;;    I1MACH( 3) = the standard punch unit.
  1124. ;;    I1MACH( 4) = the standard error message unit.
  1125. ;;
  1126. ;;  Words.
  1127. ;;    I1MACH( 5) = the number of bits per integer storage unit.
  1128. ;;    I1MACH( 6) = the number of characters per integer storage unit.
  1129. ;;
  1130. ;;  Integers.
  1131. ;;    assume integers are represented in the S-digit, base-A form
  1132. ;;
  1133. ;;               sign ( X(S-1)*A**(S-1) + ... + X(1)*A + X(0) )
  1134. ;;
  1135. ;;               where 0 .LE. X(I) .LT. A for I=0,...,S-1.
  1136. ;;    I1MACH( 7) = A, the base.
  1137. ;;    I1MACH( 8) = S, the number of base-A digits.
  1138. ;;    I1MACH( 9) = A**S - 1, the largest magnitude.
  1139. ;;
  1140. ;;  Floating-Point Numbers.
  1141. ;;    Assume floating-point numbers are represented in the T-digit,
  1142. ;;    base-B form
  1143. ;;               sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) )
  1144. ;;
  1145. ;;               where 0 .LE. X(I) .LT. B for I=1,...,T,
  1146. ;;               0 .LT. X(1), and EMIN .LE. E .LE. EMAX.
  1147. ;;    I1MACH(10) = B, the base.
  1148. ;;
  1149. ;;  Single-Precision
  1150. ;;    I1MACH(11) = T, the number of base-B digits.
  1151. ;;    I1MACH(12) = EMIN, the smallest exponent E.
  1152. ;;    I1MACH(13) = EMAX, the largest exponent E.
  1153. ;;
  1154. ;;  Double-Precision
  1155. ;;    I1MACH(14) = T, the number of base-B digits.
  1156. ;;    I1MACH(15) = EMIN, the smallest exponent E.
  1157. ;;    I1MACH(16) = EMAX, the largest exponent E.
  1158. (defun i1mach (i)
  1159.   (ecase i
  1160.     ;; What does the unit numbers really mean in Lisp?  What do we
  1161.     ;; really want?
  1162.     
  1163.     ;; The standard input unit
  1164.     (1 5)
  1165.     ;; The standard output unit
  1166.     (2 6)
  1167.     ;; The standard punch unit
  1168.     (3 6)
  1169.     ;; The standard error message unit
  1170.     (4 6)
  1171.  
  1172.     ;; The number of bits per integer storage unit.  What does this
  1173.     ;; mean in Lisp?
  1174.     (5
  1175.      (integer-length most-positive-fixnum))
  1176.     ;; The number of characters per integer storage unit.  What does
  1177.     ;; this mean in Lisp?
  1178.     (6 4)
  1179.  
  1180.     ;; The base of integers.  Assume 2's complement
  1181.     (7 2)
  1182.     ;; The number of base-2 digits.  Assume fixnum size?
  1183.     (8 (integer-length most-positive-fixnum))
  1184.     ;; The largest magnitude
  1185.     (9 most-positive-fixnum)
  1186.  
  1187.     ;; Base of floating-poing representation
  1188.     (10 (float-radix 1f0))
  1189.     ;; Number of digits in representation
  1190.     (11 (float-digits 1f0))
  1191.     ;; Smallest exponent
  1192.     (12 (multiple-value-bind (frac exp sign)
  1193.         (decode-float least-positive-normalized-single-float)
  1194.       (declare (ignore frac sign))
  1195.       (+ exp 1)))
  1196.     ;; Largest exponent
  1197.     (13 (multiple-value-bind (frac exp sign)
  1198.         (decode-float most-positive-single-float)
  1199.       (declare (ignore frac sign))
  1200.       (- exp 1)))
  1201.     ;; Same for double-precision
  1202.     (14 (float-digits 1d0))
  1203.     (15 (multiple-value-bind (frac exp sign)
  1204.         (decode-float least-positive-normalized-double-float)
  1205.       (declare (ignore frac sign))
  1206.       (+ exp 1)))
  1207.     (16 (multiple-value-bind (frac exp sign)
  1208.         (decode-float most-positive-double-float)
  1209.       (declare (ignore frac sign))
  1210.       (- exp 1)))
  1211.     ))
  1212.      
  1213.  
  1214. ;;;-------------------------------------------------------------------------
  1215. ;;; end of macros.l
  1216. ;;;
  1217. ;;; $Id: f2cl-lib.lisp,v 1.3 2002/05/19 20:24:22 rtoy Exp $
  1218. ;;; $Log: f2cl-lib.lisp,v $
  1219. ;;; Revision 1.3  2002/05/19 20:24:22  rtoy
  1220. ;;; o GCL doesn't like the declarations in our max functions, so don't
  1221. ;;;   declare the variables.
  1222. ;;; o GCL doesn't like our defparameter for *lun-hash*.  Make it defvar.
  1223. ;;; o GCL doesn't have least-positive-normalized-double-float, so
  1224. ;;;   make it the same as least-positive-double-float.  Do likewise for
  1225. ;;;   single-float.
  1226. ;;;
  1227. ;;; Revision 1.2  2002/05/05 23:44:35  rtoy
  1228. ;;; Update to latest version of macros.l:
  1229. ;;; o Fixes bug in int-sub.
  1230. ;;; o GCL doesn't have least-positive-normalized float constants
  1231. ;;; o d1mach(5)/r1mach(5) wasn't being computed as accurately as it should
  1232. ;;;   have.
  1233. ;;;
  1234. ;;; Revision 1.1  2002/04/26 13:03:40  rtoy
  1235. ;;; Initial revision.
  1236. ;;;
  1237. ;;; Revision 1.46  2002/03/19 02:23:09  rtoy
  1238. ;;; According to the rules of Fortran, the initializers in a DATA
  1239. ;;; statement are supposed to be converted to match the type of the
  1240. ;;; variable that is being initialized.  Make it so by passing the
  1241. ;;; variable type to the macro DATA-IMPLIED-DO so that the conversion can
  1242. ;;; be done.
  1243. ;;;
  1244. ;;; Revision 1.45  2002/03/18 23:34:16  rtoy
  1245. ;;; Was not correctly handling some implied do loops containing multiple
  1246. ;;; variables in the loop in data statements.  Fix that and clean up some
  1247. ;;; of the processing.  (Should probably do this kind of work in the f2cl
  1248. ;;; compiler instead of at runtime, but it's only done once at runtime, so
  1249. ;;; it's not a big deal.)
  1250. ;;;
  1251. ;;; Revision 1.44  2002/03/11 16:44:00  rtoy
  1252. ;;; o Remove an extra paren.
  1253. ;;; o Indent FIND-ARRAY-DATA better.
  1254. ;;; o Declare the iteration count to be of type INTEGER4.
  1255. ;;; o Added macros INT-ADD, INT-SUB, INT-MUL to tell the compiler that the
  1256. ;;;   integer operation can't overflow.  (First try.)
  1257. ;;; o Tell the compiler that the result of truncate is an INTEGER4 in INT.
  1258. ;;;
  1259. ;;; Revision 1.43  2002/03/06 23:07:19  rtoy
  1260. ;;; o Make INT return an integer4 type, not integer.
  1261. ;;; o log10 was thinking it could generate complex result, but that's not
  1262. ;;;   true.  Declare the arg correctly so the compiler knows it can't.
  1263. ;;;
  1264. ;;; Revision 1.42  2002/03/06 03:21:16  rtoy
  1265. ;;; o Speed up FIND-ARRAY-DATA a little by declaring the offset to be a
  1266. ;;;   fixnum, which it has to be since it's an index to an array.
  1267. ;;; o Remove the truncate/ftruncate-towards-zero functions.
  1268. ;;; o For INT, AINT, and friends, TRUNCATE and FTRUNCATE are the right
  1269. ;;;   functions we want to use.  (Stupid me!)
  1270. ;;; o Update/correct some random comments.
  1271. ;;;
  1272. ;;; Revision 1.41  2002/02/17 15:55:29  rtoy
  1273. ;;; o For all array accessors, wrap the offset calculations with (the
  1274. ;;;   fixnum ...) since they have to be anyway.  Speeds up calculations
  1275. ;;;   quite a bit.
  1276. ;;; o FREF takes an additional optional OFFSET arg to specify an offset
  1277. ;;;   for the new array slicing method.
  1278. ;;; o Added WITH-ARRAY-DATA and FIND-ARRAY-DATA to support the new
  1279. ;;;   array-slicing method.
  1280. ;;; o For FDO, add (the integer4 ...) for loop index calculations.
  1281. ;;; o Add some more assertions for ISIGN and LOG10 to help the compiler
  1282. ;;;   generate better code.
  1283. ;;;
  1284. ;;; Revision 1.40  2002/02/10 03:43:51  rtoy
  1285. ;;; Partial support for WRITE statements writing to a string instead of
  1286. ;;; logical unit.
  1287. ;;;
  1288. ;;; Revision 1.39  2002/02/09 15:59:26  rtoy
  1289. ;;; o Add more and better comments
  1290. ;;; o AINT was broken because it should accept any range of floats.
  1291. ;;; o DIM and friends computed the wrong thing!
  1292. ;;; o Change DPROD to convert to doubles first.
  1293. ;;; o Some cleanup of MAX and MIN
  1294. ;;;
  1295. ;;; Revision 1.38  2002/02/08 23:38:36  rtoy
  1296. ;;; Use ARRAY-TOTAL-SIZE to compute how many elements are in the slice
  1297. ;;; instead of the f2cl declared/derived bounds so that we can dynamically
  1298. ;;; change the size of the array.  Useful for an array in a common block.
  1299. ;;;
  1300. ;;; Revision 1.37  2002/02/07 03:23:15  rtoy
  1301. ;;; Add functions to initialize F2CL's Fortran I/O and to close all of
  1302. ;;; F2CL's open units.
  1303. ;;;
  1304. ;;; Revision 1.36  2002/02/04 03:23:46  rtoy
  1305. ;;; o Make *lun-hash* a defparameter instead of a defvar.
  1306. ;;; o Fix up i1mach so that the unit numbers match *lun-hash*.
  1307. ;;;
  1308. ;;; Revision 1.35  2002/01/13 16:29:00  rtoy
  1309. ;;; o This file is in the f2cl-lib package now
  1310. ;;; o Deleted some unused code.
  1311. ;;; o Moved *INTRINSIC-FUNCTION-NAMES* to f2cl1.l
  1312. ;;;
  1313. ;;; Revision 1.34  2002/01/06 23:11:04  rtoy
  1314. ;;; o Rename *intrinsic_function_names* to use dashes.
  1315. ;;; o Comment out some unused functions and macros.
  1316. ;;;
  1317. ;;; Revision 1.33  2001/04/30 15:38:12  rtoy
  1318. ;;; Add a version of I1MACH.
  1319. ;;;
  1320. ;;; Revision 1.32  2001/04/26 17:49:19  rtoy
  1321. ;;; o SIGN and DIM are Fortran generic instrinsics.  Make it so.
  1322. ;;; o Added D1MACH and R1MACH because they're very common in Fortran
  1323. ;;;   libraries.
  1324. ;;;
  1325. ;;; Revision 1.31  2001/02/26 15:38:23  rtoy
  1326. ;;; Move *check-array-bounds* from f2cl1.l to macros.l since the generated
  1327. ;;; code refers to it.  Export this variable too.
  1328. ;;;
  1329. ;;; Revision 1.30  2000/08/30 17:00:42  rtoy
  1330. ;;; o In EXECUTE-FORMAT, handle the case where the group is supposed to be
  1331. ;;;   repeated "forever" (as indicated by a repetition factor of T).
  1332. ;;; o Remove some more unused code.
  1333. ;;;
  1334. ;;; Revision 1.29  2000/08/27 16:36:07  rtoy
  1335. ;;; Clean up handling of format statements.  Should handle many more
  1336. ;;; formats correctly now.
  1337. ;;;
  1338. ;;; Revision 1.28  2000/08/07 19:00:47  rtoy
  1339. ;;; Add type ARRAY-STRINGS to denote an array of strings.
  1340. ;;;
  1341. ;;; Revision 1.27  2000/08/03 13:45:53  rtoy
  1342. ;;; Make FFORMAT1 handle lists that we get from implied do loops.
  1343. ;;;
  1344. ;;; The whole FFORMAT stuff needs to be rethought if we really want to
  1345. ;;; support Fortran output.
  1346. ;;;
  1347. ;;; Revision 1.26  2000/08/01 22:10:41  rtoy
  1348. ;;; o Try to make the Fortran functions to convert to integers work the
  1349. ;;;   way Fortran says they should.
  1350. ;;; o Declaim most of the intrinsics as inline so we don't have an
  1351. ;;;   additional function call for simple things.
  1352. ;;; o Add some compiler macros for Fortran max/min functions to call the
  1353. ;;;   Lisp max/min functions withouth using #'apply.
  1354. ;;; o Try to declare the args to functions with branchs appropriately,
  1355. ;;;   even in the face of signed zeroes.
  1356. ;;;
  1357. ;;; Revision 1.25  2000/07/28 22:10:05  rtoy
  1358. ;;; Remove unused var from ARRAY-SLICE.
  1359. ;;;
  1360. ;;; Revision 1.24  2000/07/28 17:09:13  rtoy
  1361. ;;; o We are in the f2cl package now.
  1362. ;;; o Remove the export expression.
  1363. ;;; o // is now called F2CL-//, to prevent problems with the lisp variable
  1364. ;;;   //.
  1365. ;;; o REAL is now called FREAL, to prevent problems with the lisp type
  1366. ;;;   REAL.
  1367. ;;;
  1368. ;;; Revision 1.23  2000/07/27 16:39:17  rtoy
  1369. ;;; We want to be in the CL-USER package, not the USER package.
  1370. ;;;
  1371. ;;; Revision 1.22  2000/07/20 13:44:38  rtoy
  1372. ;;; o Remove old fref macro
  1373. ;;; o Add some comments
  1374. ;;; o Add macro ARRAY-INITIALIZE to handle creating the appropriate for to
  1375. ;;;   give to make-array :initial-contents.
  1376. ;;;
  1377. ;;; Revision 1.21  2000/07/19 13:54:27  rtoy
  1378. ;;; o Add the types ARRAY-DOUBLE-FLOAT, ARRAY-SINGLE-FLOAT, and
  1379. ;;;   ARRAY-INTEGER4.
  1380. ;;; o All arrays are 1-D now to support slicing of Fortran arrays
  1381. ;;;   correctly.
  1382. ;;; o All arrays are in column-major order just like Fortran (and the
  1383. ;;;   opposite of Lisp).  This is to support slicing of arrays.  Modified
  1384. ;;;   FREF to support this by taking an extra arg for the dimensions of
  1385. ;;;   the array.
  1386. ;;; o Added macro ARRAY-SLICE to slice the array properly.
  1387. ;;; o Optimized routine DMIN1 a bit.   (Need to do that for more routines.)
  1388. ;;;
  1389. ;;; Revision 1.20  2000/07/14 15:50:59  rtoy
  1390. ;;; Get rid of *dummy_var*.  It's not used anymore.
  1391. ;;;
  1392. ;;; Revision 1.19  2000/07/13 16:55:34  rtoy
  1393. ;;; To satisfy the Copyright statement, we have placed the RCS logs in
  1394. ;;; each source file in f2cl.  (Hope this satisfies the copyright.)
  1395. ;;;
  1396. ;;;-----------------------------------------------------------------------------
  1397.